package com.lonely.order.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lonely.common.core.domain.TimeLine;
import com.lonely.common.enums.CommonStatus;
import com.lonely.common.utils.SecurityUtils;
import com.lonely.goods.domain.dto.log.AddNotesDTO;
import com.lonely.goods.domain.vo.log.OrderNoteLogVO;
import com.lonely.order.domain.dto.order.AddOrderLogDTO;
import com.lonely.order.domain.entity.SysOrder;
import com.lonely.order.domain.entity.SysOrderLog;
import com.lonely.order.enums.OrderLogEnum;
import com.lonely.order.mapper.SysOrderLogMapper;
import com.lonely.order.service.IOrderLogService;
import com.lonely.order.service.IOrderService;
import com.lonely.system.domain.entity.SysFactory;
import com.lonely.system.service.ISysFactoryService;
import com.lonely.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static cn.hutool.core.date.DatePattern.NORM_DATETIME_MINUTE_FORMAT;

/**
 * 订单日志服务实现类
 *
 * @author fzzf
 */
@Service
public class OrderLogServiceImpl extends ServiceImpl<SysOrderLogMapper, SysOrderLog> implements IOrderLogService {

    @Autowired
    private ISysFactoryService sysFactoryService;

    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    private IOrderService orderService;

    /**
     * 获取指定订单号的日志时间线
     *
     * @param produceOrderId
     * @return
     */
    @Override
    public List<TimeLine> getOrderLogTimeLine(Long produceOrderId) {
        SysOrder sysOrder = this.orderService.getOne(new LambdaQueryWrapper<SysOrder>().eq(SysOrder::getProduceOrderId, produceOrderId)
                .eq(SysOrder::getStatus, CommonStatus.ENABLE.code));
        Assert.notNull(sysOrder, "订单不存在");

        return super.list(new LambdaQueryWrapper<SysOrderLog>().eq(SysOrderLog::getOrderId, sysOrder.getId())
                        .eq(SysOrderLog::getStatus, CommonStatus.ENABLE.code)
                        .orderByDesc(SysOrderLog::getCreateTime,SysOrderLog::getId))
                .stream().map(sysOrderLog -> {
                    TimeLine timeLine = new TimeLine();
                    timeLine.setType(this.convertTimeLineType(sysOrderLog.getType()));
                    timeLine.setContent(sysOrderLog.getLogBody());
                    timeLine.setTitle(sysOrderLog.getLogTitle());
                    timeLine.setTime(DateUtil.formatDateTime(sysOrderLog.getCreateTime()));
                    return timeLine;
                }).collect(Collectors.toList());
    }

    /**
     * 添加备注
     *
     * @param addNotes
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addNotes(AddNotesDTO addNotes) {
        SysOrderLog sysOrderLog = new SysOrderLog();
        sysOrderLog.setOrderId(addNotes.getOrderId());
        sysOrderLog.setLogTitle(generatorLogBodyByCurrentUser());
        sysOrderLog.setLogBody(addNotes.getNotes());
        sysOrderLog.setType(OrderLogEnum.LogTypeEnum.NOTES.getType());
        sysOrderLog.setCreateBy(SecurityUtils.getUserId());
        sysOrderLog.setUpdateBy(SecurityUtils.getUserId());

        super.save(sysOrderLog);
    }

    /**
     * 获取指定订单的备注日志列表
     *
     * @param orderId
     * @return
     */
    @Override
    public List<OrderNoteLogVO> getOrderNoteLogs(Long orderId) {
        return super.list(new LambdaQueryWrapper<SysOrderLog>().eq(SysOrderLog::getOrderId, orderId)
                        .eq(SysOrderLog::getStatus, CommonStatus.ENABLE.code)
                        .eq(SysOrderLog::getType, OrderLogEnum.LogTypeEnum.NOTES.getType())
                        .orderByDesc(SysOrderLog::getCreateTime))
                .stream().map(sysOrderLog -> {
                    OrderNoteLogVO orderNoteLogVO = new OrderNoteLogVO();
                    orderNoteLogVO.setId(sysOrderLog.getId());
                    orderNoteLogVO.setNoteBody(sysOrderLog.getLogBody());
                    orderNoteLogVO.setNoteTime(DateUtil.format(sysOrderLog.getCreateTime(), NORM_DATETIME_MINUTE_FORMAT));
                    orderNoteLogVO.setNoteUserName(this.sysUserService.getUserNameById(Convert.toLong(sysOrderLog.getCreateBy())));
                    return orderNoteLogVO;
                }).collect(Collectors.toList());
    }

    /**
     * 获取指定订单id集合对应的订单日志中包含备注类型的订单id
     *
     * @param orderIds
     * @return
     */
    @Override
    public Set<Long> hasOrderNoteLogByOrderIds(List<Long> orderIds) {
        if (CollUtil.isEmpty(orderIds)) {
            return new HashSet<>();
        }
        return super.list(new LambdaQueryWrapper<SysOrderLog>()
                        .select(SysOrderLog::getOrderId)
                        .eq(SysOrderLog::getType, OrderLogEnum.LogTypeEnum.NOTES.getType())
                        .in(SysOrderLog::getOrderId, orderIds)
                        .eq(SysOrderLog::getStatus, CommonStatus.ENABLE.code))
                .stream()
                .map(SysOrderLog::getOrderId)
                .collect(Collectors.toSet());
    }

    /**
     * 添加订单日志
     *
     * @param orderId
     * @param message
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addOrderLog(Long orderId, String message) {
        // 获取当前工厂名称
        String factoryName = this.sysFactoryService.getFactoryName(SecurityUtils.getFactoryId());
        SysOrderLog sysOrderLog = this.buildOrderLog(orderId, message, factoryName);
        super.save(sysOrderLog);
    }

    /**
     * 批量添加订单日志
     *
     * @param addOrderLogs
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchAddOrderLog(List<AddOrderLogDTO> addOrderLogs) {
        if (CollUtil.isEmpty(addOrderLogs)) {
            return;
        }

        // 获取当前工厂名称
        String factoryName = this.sysFactoryService.getFactoryName(SecurityUtils.getFactoryId());
        List<SysOrderLog> orderLogs = addOrderLogs.stream().map(x -> buildOrderLog(x.getOrderId(), x.getTitle(), factoryName)).collect(Collectors.toList());
        super.saveBatch(orderLogs);
    }

    /**
     * 构建订单日志对象
     *
     * @param orderId
     * @param title
     * @param factoryName
     * @return
     */
    private SysOrderLog buildOrderLog(Long orderId, String title, String factoryName) {
        SysOrderLog sysOrderLog = new SysOrderLog();
        sysOrderLog.setOrderId(orderId);
        sysOrderLog.setLogTitle(title);
        sysOrderLog.setLogBody(String.format("%s-%s-%s", factoryName, SecurityUtils.getUsername(), SecurityUtils.getLoginUser().getUser().getPhone()));
        sysOrderLog.setStatus(CommonStatus.ENABLE.code);
        sysOrderLog.setType(OrderLogEnum.LogTypeEnum.STATUS.getType());
        sysOrderLog.setCreateBy(SecurityUtils.getUserId());
        sysOrderLog.setUpdateBy(SecurityUtils.getUserId());
        return sysOrderLog;
    }


    /**
     * 基于当前登录用户构建日志body
     *
     * @return
     */
    private String generatorLogBodyByCurrentUser() {
        Long factoryId = SecurityUtils.getFactoryId();
        SysFactory factory = this.sysFactoryService.getById(factoryId);
        Assert.notNull(factory, "工厂不存在");
        return String.format("%s-%s-%s", factory.getName(), SecurityUtils.getUsername(), SecurityUtils.getLoginUser().getUser().getPhone());
    }

    /**
     * 根据日志类型获取对应时间线类型
     *
     * @param logType
     * @return
     */
    private String convertTimeLineType(int logType) {
        OrderLogEnum.LogTypeEnum instance = OrderLogEnum.LogTypeEnum.getInstance(logType);
        switch (instance) {
            case STATUS:
                return "success";
            case NOTES:
                return "info";
        }
        return "default";
    }
}
